using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;
using BriansClimb.Climber;

namespace BriansClimb.DrawableGameObjects.ClimbingHolds
{
    /// <summary>
    /// This is the climbing hold object that is placed on the wall 
    /// and the climber grabs.
    /// </summary>
    public class ClimbingHold : Microsoft.Xna.Framework.DrawableGameComponent
    {
        protected Game game;
        protected SpriteBatch spriteBatch;
        //!Texture for the rest hold
        protected Texture2D restHold;
        //!Texture for the jug hold
        protected Texture2D jugHold;
        //!Texture for the crimp hold
        protected Texture2D crimpHold;
        //!Texture for the slope hold
        protected Texture2D slopeHold;
        //!Texture for the foot hold
        protected Texture2D footHold;
        //!Current hold's texture
        protected Texture2D currentHold;
        protected Vector2 climbingHoldPosition;
        protected string climbingHoldType;
        //!Bodypart object associated with the hold
        protected BodyPart holdBodyObject;
        protected int friction;
        //!The number of hands or feet that are holding teh hold
        protected int holdCount = 0;
        protected int greedyValue;
        protected bool isHeld = false;
        protected string heldBy;
        protected bool isRed = false;
        //!If the rest hold capability has been used(if its a rest hold)
        protected bool holdUsed = false;
        
        //!Red color byte value
        protected int redByte = 0;
        //!Blue color byte value
        protected int blueByte = 240;
        //!Green color byte value
        protected int greenByte = 175;
        protected byte rV, bV, gV;
        //!Iterator used for changing color
        protected int itCount = 0;
        //!Speed the color changes
        protected int colorChangeSpeed = 25;


        /// <summary>
        /// Default Constructor
        /// </summary>
        /// <param name="game">Main Game Object</param>
        /// <param name="coordinates">Vector2 Coordinates of Climbing Hold</param>
        /// <param name="climbingHoldType">String Variable Specifying Climbing Hold Type</param>
        public ClimbingHold(Game game, Vector2 coordinates, string climbingHoldType,
                    int friction, BodyPart holdBodyIn)
            : base(game)
        {
            this.game = game;
            spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));

            climbingHoldPosition = coordinates;
            this.climbingHoldType = climbingHoldType;
            this.friction = friction;
            holdBodyObject = holdBodyIn;
            greedyValue = 0;

            //Loading Textures
            restHold = game.Content.Load<Texture2D>(".\\Textures\\HoldRest");
            jugHold = game.Content.Load<Texture2D>(".\\Textures\\HoldJug");
            crimpHold = game.Content.Load<Texture2D>(".\\Textures\\HoldCrimp");
            slopeHold = game.Content.Load<Texture2D>(".\\Textures\\HoldSloper");
            footHold = game.Content.Load<Texture2D>(".\\Textures\\HoldFoot");            
        }

        /// <summary>
        /// Base contsructor
        /// </summary>
        /// <param name="game">Main game object</param>
        public ClimbingHold(Game game)
            : base(game)
        {
            this.game = game;
        }

        /// <summary>
        /// Allows the game component to perform any initialization it needs to before starting
        /// to run.  This is where it can query for any required services and load content.
        /// </summary>
        public override void Initialize()
        {
            // TODO: Add your initialization code here

            base.Initialize();
        }

        /// <summary>
        /// Attribute representing the climbing hold coordinates.
        /// </summary>
        public Vector2 ClimbingHoldPosition
        {
            get { return climbingHoldPosition; }
        }

        /// <summary>
        /// Attribute representing the red byte of the color of the hold.
        /// </summary>
        public int RedByte
        {
            get { return redByte; }
        }

        /// <summary>
        /// Attribute representing the BodyPart of the hold.
        /// </summary>
        public BodyPart HoldBodyPart
        {
            get { return holdBodyObject; }
            set { holdBodyObject = value; }
        }

        /// <summary>
        /// Attribute representing the type of hold the hold is.
        /// </summary>
        public string ClimbingHoldType
        {
            get { return climbingHoldType; }
            set { climbingHoldType = value;  } 
        }

        /// <summary>
        /// Attribute representing the friction of the hold.
        /// </summary>
        public int HoldFriction
        {
            get { return friction; }
            set { friction = value; }
        }

        /// <summary>
        /// Attribute representing the speed at which the color of the hold changes.
        /// </summary>
        public int ColorSpeed
        {
            get { return colorChangeSpeed; }
            set { colorChangeSpeed = value; }
        }

        /// <summary>
        /// Attribute representing whether the hold is red or not.
        /// </summary>
        public bool HoldIsRed
        {
            get { return isRed; }
            set { isRed = value; }
        }
        
        /// <summary>
        /// Attribute representing if the hold is being held or not
        /// </summary>
        public bool IsBeingHeld
        {
            get { return isHeld; }
            set { isHeld = value; }
        }

        /// <summary>
        /// Attribute representing the body part in the climber that is holding the hold.
        /// </summary>
        public String HeldBy
        {
            get { return heldBy; }
            set { heldBy = value; }
        }

        /// <summary>
        /// The greedy value of the hold that the climber AI assigns to it.  Depricated.
        /// </summary>
        public int GreedyValue
        {
            get { return greedyValue; }
            set { greedyValue = value; }
        }

        /// <summary>
        /// The number of body parts that are holding the hold.
        /// </summary>
        public int HoldCount
        {
            get { return holdCount; }
            set { holdCount = value; }
        }

        /// <summary>
        /// Attribute to indicate, if the hold is a rest hold, if it has been used.
        /// </summary>
        public bool HoldUsed
        {
            get { return holdUsed; }
            set { holdUsed = value; }
        }

        /// <summary>
        /// Will perform a check to see if the climber has made contact with a 
        /// hold and then adjust the color of the hold.
        /// </summary>
        public void ColorHolds()
        {
            
            if (isHeld)
            {
                /*
                 * If the hold is being held, decrement the blue and green bytes by one
                 * and increment the red byte by one.
                 */
                
                
                if (blueByte > 1)                
                    blueByte--;                                                      

                if (greenByte > 1)                
                    greenByte--;

                if (redByte < 255)
                    redByte++ ;
                
            }
            else
            {
                /* If the hold is not being held and the green and blue bytes are less
                 * than default, increment them and decrement the red byte until it is
                 * zero.
                 */

                if (blueByte < 240)
                    blueByte++;

                if (greenByte < 175)
                    greenByte++;

                if (redByte > 0)
                    redByte--;
                
            }         

            //Set the isRed variable to true if the red byte color is fully red.
            if (redByte > 253)
            {
                isRed = true;                
            }

            //Convert int values into byte values for actual color change.
            rV = (byte)redByte;
            gV = (byte)greenByte;
            bV = (byte)blueByte;
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            /* Checks which type of climbing hold is required then sets that climbing hold texture as
             * the currentHold
             */
            switch (climbingHoldType)
            {
                case "rest":
                    currentHold = restHold;
                    break;
                case "jug":
                    currentHold = jugHold;
                    break;
                case "crimp":
                    currentHold = crimpHold;
                    break;
                case "slope":
                    currentHold = slopeHold;
                    break;
                case "foot":
                    currentHold = footHold;
                    break;
            }

            //The iteration that determines how often the color changes its hue.
            itCount++;
            if ((itCount > colorChangeSpeed) && (climbingHoldType != "rest"))
            {
                ColorHolds();
                itCount = 0;
            }                      
            
            base.Update(gameTime);
        }

        /// <summary>
        /// Allows the game component to draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values</param>
        public override void Draw(GameTime gameTime)
        {             
            //Draws the rest hold without tint, and regular holds with tint.
            if(climbingHoldType != null)
                if(climbingHoldType == "rest")
                    spriteBatch.Draw(currentHold, climbingHoldPosition, null, Color.White,
                        0, new Vector2(currentHold.Width / 2, currentHold.Height / 2), 1, SpriteEffects.None, 0);
                else
                    spriteBatch.Draw(currentHold, climbingHoldPosition, null, new Color(rV, gV, bV), 
                        0, new Vector2(currentHold.Width / 2, currentHold.Height / 2), 1, SpriteEffects.None, 0);
            base.Draw(gameTime);
        }
    }
}